f63dc2
@@ -211,27 +211,32 @@
public ObjectInspector apply(PrimitiveTypeInfo type) {
       Query<?> query;
       try {
         query = DruidStorageHandlerUtils.JSON_MAPPER.readValue(druidQuery, Query.class);
+
+        switch (query.getType()) {
+          case Query.TIMESERIES:
+            inferSchema((TimeseriesQuery) query, columnNames, columnTypes);
+            break;
+          case Query.TOPN:
+            inferSchema((TopNQuery) query, columnNames, columnTypes);
+            break;
+          case Query.SELECT:
+            String address = HiveConf.getVar(configuration,
+                    HiveConf.ConfVars.HIVE_DRUID_BROKER_DEFAULT_ADDRESS);
+            if (org.apache.commons.lang3.StringUtils.isEmpty(address)) {
+              throw new SerDeException("Druid broker address not specified in configuration");
+            }
+            inferSchema((SelectQuery) query, columnNames, columnTypes, address);
+            break;
+          case Query.GROUP_BY:
+            inferSchema((GroupByQuery) query, columnNames, columnTypes);
+            break;
+          default:
+            throw new SerDeException("Not supported Druid query");
+        }
       } catch (Exception e) {
         throw new SerDeException(e);
       }
 
-      switch (query.getType()) {
-        case Query.TIMESERIES:
-          inferSchema((TimeseriesQuery) query, columnNames, columnTypes);
-          break;
-        case Query.TOPN:
-          inferSchema((TopNQuery) query, columnNames, columnTypes);
-          break;
-        case Query.SELECT:
-          inferSchema((SelectQuery) query, columnNames, columnTypes);
-          break;
-        case Query.GROUP_BY:
-          inferSchema((GroupByQuery) query, columnNames, columnTypes);
-          break;
-        default:
-          throw new SerDeException("Not supported Druid query");
-      }
-
       columns = new String[columnNames.size()];
       types = new PrimitiveTypeInfo[columnNames.size()];
       for (int i = 0; i < columnTypes.size(); ++i) {
@@ -303,6 +308,9 @@
private void inferSchema(TimeseriesQuery query, List<String> columnNames,
       columnTypes.add(DruidSerDeUtils.convertDruidToHiveType(af.getTypeName()));
     }
     // Post-aggregator columns
+    // TODO: Currently Calcite only infers avg for post-aggregate,
+    // but once we recognize other functions, we will need to infer
+    // different types for post-aggregation functions
     for (PostAggregator pa : query.getPostAggregatorSpecs()) {
       columnNames.add(pa.getName());
       columnTypes.add(TypeInfoFactory.floatTypeInfo);
@@ -325,6 +333,9 @@
private void inferSchema(TopNQuery query, List<String> columnNames,
       columnTypes.add(DruidSerDeUtils.convertDruidToHiveType(af.getTypeName()));
     }
     // Post-aggregator columns
+    // TODO: Currently Calcite only infers avg for post-aggregate,
+    // but once we recognize other functions, we will need to infer
+    // different types for post-aggregation functions
     for (PostAggregator pa : query.getPostAggregatorSpecs()) {
       columnNames.add(pa.getName());
       columnTypes.add(TypeInfoFactory.floatTypeInfo);
@@ -333,8 +344,7 @@
private void inferSchema(TopNQuery query, List<String> columnNames,
 
   /* Select query */
   private void inferSchema(SelectQuery query, List<String> columnNames,
-          List<PrimitiveTypeInfo> columnTypes
-  ) {
+          List<PrimitiveTypeInfo> columnTypes, String address) throws SerDeException {
     // Timestamp column
     columnNames.add(DruidTable.DEFAULT_TIMESTAMP_COLUMN);
     columnTypes.add(TypeInfoFactory.timestampTypeInfo);
@@ -343,10 +353,27 @@
private void inferSchema(SelectQuery query, List<String> columnNames,
       columnNames.add(ds.getOutputName());
       columnTypes.add(TypeInfoFactory.stringTypeInfo);
     }
-    // Metric columns
+    // The type for metric columns is not explicit in the query, thus in this case
+    // we need to emit a metadata query to know their type
+    SegmentMetadataQueryBuilder builder = new Druids.SegmentMetadataQueryBuilder();
+    builder.dataSource(query.getDataSource());
+    builder.merge(true);
+    builder.analysisTypes();
+    SegmentMetadataQuery metadataQuery = builder.build();
+    // Execute query in Druid
+    SegmentAnalysis schemaInfo;
+    try {
+      schemaInfo = submitMetadataRequest(address, metadataQuery);
+    } catch (IOException e) {
+      throw new SerDeException(e);
+    }
+    if (schemaInfo == null) {
+      throw new SerDeException("Connected to Druid but could not retrieve datasource information");
+    }
     for (String metric : query.getMetrics()) {
       columnNames.add(metric);
-      columnTypes.add(TypeInfoFactory.floatTypeInfo);
+      columnTypes.add(DruidSerDeUtils.convertDruidToHiveType(
+              schemaInfo.getColumns().get(metric).getType()));
     }
   }
 
@@ -368,6 +395,9 @@
private void inferSchema(GroupByQuery query, List<String> columnNames,
       columnTypes.add(DruidSerDeUtils.convertDruidToHiveType(af.getTypeName()));
     }
     // Post-aggregator columns
+    // TODO: Currently Calcite only infers avg for post-aggregate,
+    // but once we recognize other functions, we will need to infer
+    // different types for post-aggregation functions
     for (PostAggregator pa : query.getPostAggregatorSpecs()) {
       columnNames.add(pa.getName());
       columnTypes.add(TypeInfoFactory.floatTypeInfo);
